#![allow(unused, unused_variables, dead_code)]

use salvo::catcher::Catcher;
use salvo::conn::rustls::{Keycert, RustlsConfig};
use salvo::prelude::*;
use tokio::sync::oneshot;
use tracing::info;

use config::{CERT_KEY, CFG};


use crate::middleware::handle_404::handle_404;
use crate::routers::router;
use crate::di::AppContainer;
use config::db::init_db_conn;
use halo_model::prelude::*;
use macros::gvk;

mod config;
mod extension;
mod store;
mod middleware;
mod routers;
mod services;
mod tests;
mod utils;
mod infra;
mod di;
mod scheme_manager_solution_test;

#[tokio::main]
async fn main() {
    //At the same time, logs are only output to the terminal or file
    init_log();
    init_db_conn().await;
    init_app().await;
    let (tx, rx) = oneshot::channel();
    let router = router();
    let service: Service = router.into();
    let service = service.catcher(Catcher::default().hoop(handle_404));
    info!("💨 {} is staring ", &CFG.server.name);
    info!(" listen on {}", &CFG.server.address);

    match CFG.server.ssl {
        true => {
            info!(
                "swagger-ui: https://{}/swagger-ui",
                &CFG.server.address.replace("0.0.0.0", "127.0.0.1")
            );
            let config = RustlsConfig::new(
                Keycert::new()
                    .cert(CERT_KEY.cert.clone())
                    .key(CERT_KEY.key.clone()),
            );
            let acceptor = TcpListener::new(&CFG.server.address)
                .rustls(config)
                .bind()
                .await;
            let server = Server::new(acceptor).serve_with_graceful_shutdown(
                service,
                async {
                    rx.await.ok();
                },
                None,
            );
            tokio::task::spawn(server);
        }
        false => {
            info!(
                "swagger-ui: http://{}/swagger-ui",
                &CFG.server.address.replace("0.0.0.0", "127.0.0.1")
            );
            let acceptor = TcpListener::new(&CFG.server.address).bind().await;
            let server = Server::new(acceptor).serve_with_graceful_shutdown(
                service,
                async {
                    rx.await.ok();
                },
                None,
            );
            tokio::task::spawn(server);
        }
    };
    // Wait for Ctrl-C
    tokio::signal::ctrl_c().await.unwrap();
    // Then, start the shutdown...
    let _ = tx.send(());
}

fn init_log() {
    let _guard = clia_tracing_config::build()
        .filter_level(&CFG.log.filter_level)
        .with_ansi(CFG.log.with_ansi)
        .to_stdout(CFG.log.to_stdout)
        .directory(&CFG.log.directory)
        .file_name(&CFG.log.file_name)
        .rolling(&CFG.log.rolling)
        .init();
    info!("log level: {}", &CFG.log.filter_level);
}

async fn init_app() {
    // init_scheme().await; // 移除，因为 SchemeManager 现在通过依赖注入管理

    // 初始化依赖注入容器
    if let Err(e) = init_dependency_injection().await {
        panic!("Failed to initialize dependency injection: {}", e);
    }
}

async fn init_dependency_injection() -> anyhow::Result<()> {
    // 获取数据库连接
    let db_connection = config::db::DB.get()
        .ok_or_else(|| anyhow::anyhow!("Database connection not initialized"))?
        .clone();

    // 获取配置
    let config = CFG.clone();

    // 初始化应用容器
    AppContainer::initialize(db_connection, config).await?;

    info!("Dependency injection container initialized successfully");
    Ok(())
}
